package IC.lir;

import java.util.*;

import IC.AST.ASTNode;
import IC.AST.StaticFunctionCall;
import IC.SymbolTables.Types.ArrayType;
import IC.SymbolTables.Types.MethodType;
import IC.SymbolTables.Types.VoidType;
import IC.SymbolTables.Types.BasicType.BasicTypeEnum;
import IC.lir.Instrunction.*;

public class LirFunction 
{
	public static final String MainLabelString = "_ic_main";
	
	private LinkedList<Instruction> _impl = new LinkedList<Instruction>();
	public void SetImpl(LinkedList<Instruction> impl) { _impl = new LinkedList<Instruction>(impl); } 
	public LinkedList<Instruction> GetImpl() { return _impl; }
	
	public LirFunction(LabelDecl label, LinkedList<Instruction> impl, IC.AST.Method node)
	{
		SetLabel(label);
		SetImpl(impl);
		SetASTNode(node);
	}
	
	private IC.AST.Method _ASTNode;
	public IC.AST.Method GetASTNode() { return _ASTNode; }
	public void SetASTNode(IC.AST.Method method) { _ASTNode = method; }
	
	private LabelDecl _label;
	public void SetLabel(LabelDecl label) { _label = label;}
	public Label GetLabel() { return _label; }
	
	public String toString()
	{
		String ret = String.format("%s\n", _label.toString());
		for (Instruction i : _impl)
			ret += i.toString() + "\n";
		
		return IC.Utils.TrimLast(ret, 1);
	}
	
	public static String GenerateLIRFuncName(String classID, String funcID, IC.AST.Method node)
	{
		return GenerateFuncLabelWithMainCheck(classID, funcID, node, node.IsStatic());
	}	
	
	public static String GenerateLIRFuncName(String classID, String funcID, IC.AST.FunctionCall node)
	{
		return GenerateFuncLabelWithMainCheck(classID, funcID, node, node instanceof StaticFunctionCall);
	}
	
	private static String GenerateFuncLabelWithMainCheck(String classID, String funcID, ASTNode node, boolean isStatic)
	{
		if (funcID.equals("main") && 
				CheckMainSignature((MethodType)node.GetType(), isStatic))
			return MainLabelString;
		return String.format("_%s_%s", classID, funcID);
	}
	
	private static boolean CheckMainSignature(MethodType signature, boolean isStatic)
	{
		return isStatic
				&& (signature.GetReturnType().equals(new VoidType()))
				&& (signature.GetParamTypes().length == 1)
				&& (signature.GetParamTypes()[0].equals(
						new ArrayType(
								new IC.SymbolTables.Types.BasicType(
										BasicTypeEnum.STRING))));
	}
}
